package fr.labri.macchiato.client.project;

import com.google.gwt.i18n.client.NumberFormat;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.util.BooleanCallback;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.IconButton;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.events.CloseClickEvent;
import com.smartgwt.client.widgets.events.CloseClickHandler;
import com.smartgwt.client.widgets.form.fields.events.KeyPressEvent;
import com.smartgwt.client.widgets.form.fields.events.KeyPressHandler;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.PortalLayout;
import com.smartgwt.client.widgets.layout.Portlet;
import com.smartgwt.client.widgets.layout.VLayout;
import com.smartgwt.client.widgets.layout.VStack;

import fr.labri.macchiato.client.cart.CartWidget;
import fr.labri.macchiato.client.share.ShareButtons;
import fr.labri.macchiato.framework.business.service.ProjectService;
import fr.labri.macchiato.framework.business.service.Services;
import fr.labri.macchiato.framework.util.FrameworkException;

/**
 * Widget displaying a project's content
 * 
 * @author Matthieu FOUCAULT
 * 
 */

public class ProjectWidget extends VStack {

	private static final String ERROR_NULL_BUDGET = "Le budget ne peut pas être vide";
	private static final String ADD_CART = "Ajouter un nouveau panier";
	private static final String ADD_CART_ICON = "/icons/plus.svg";
	private static final String CLOSE_CONFIRMATION_TITLE = "Confirmation";
	private static final String CLOSE_CONFIRMATION_MSG = "Voulez-vous vraiment supprimer ce panier ?";

	private final PortalLayout portalLayout;
	private VLayout vLayout;
	private HLayout headerLayout;
	private IconButton addCartButton;

	private String projectName;

	/**
	 * Creates a new widget for the given project
	 * 
	 * @param projectName
	 *            The name of the project for which the widget is created
	 */
	public ProjectWidget(String projectName) {
		this.projectName = projectName;
		Label projectTitle = new Label(projectName);
		projectTitle.setAutoHeight();
		projectTitle.setWidth("*");
		projectTitle.setStyleName("projectTitle");

		portalLayout = new PortalLayout(1);
		portalLayout.setWidth100();
		portalLayout.setHeight("*");
		portalLayout.setShowColumnMenus(false);
		portalLayout.setColumnBorder("none");
		portalLayout.setPreventRowUnderflow(false);
		portalLayout.setOverflow(Overflow.VISIBLE);
		portalLayout.setCanResizePortlets(false);

		vLayout = new VLayout(15);
		vLayout.setHeight100();

		headerLayout = new HLayout();
		headerLayout.setWidth100();
		headerLayout.setAutoHeight();
		headerLayout.addMember(projectTitle);

		vLayout.addMember(headerLayout);
		addShareButton();
		addProjectBudget();
		vLayout.addMember(portalLayout);
		addMember(vLayout);

		loadCarts();

	}

	private void addProjectBudget() {
		Double budget = getProjectService().getBudget(projectName);
		String stringBudget = NumberFormat.getCurrencyFormat().format(budget);
		Label budgetLabel = new Label("Budget : " + stringBudget);
		budgetLabel.setWidth100();
		budgetLabel.setStyleName("projectTitle");
		budgetLabel.setAutoHeight();
		vLayout.addMember(budgetLabel);
	}

	private void addShareButton() {
		headerLayout.addMember(ShareButtons.facebookShareButton(projectName));
		headerLayout.addMember(ShareButtons.googlePlusOneButton(projectName));
	}

	private void loadCarts() {
		for (String cartName : getProjectService().getCarts(projectName)
				.keySet())
			addCartWidget(cartName);
	}

	/**
	 * Adds the prompt to be used at the creation of a new cart
	 * 
	 * @param prompt
	 *            The prompt to be used
	 */
	public void addPromptHandlers(final AddCartPrompt prompt) {
		prompt.getValidateButton().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				cartCreationBehaviour(prompt);
			}
		});
		prompt.getTextItem().addKeyPressHandler(new KeyPressHandler() {

			@Override
			public void onKeyPress(KeyPressEvent event) {

				if (event.getKeyName().equals("Enter")) {
					cartCreationBehaviour(prompt);
				}
			}
		});
	}

	/**
	 * Getter for the add cart button
	 * 
	 * @return The button
	 */
	public Canvas getAddCartButton() {
		if (addCartButton == null) {
			addCartButton = new IconButton(ADD_CART);
			addCartButton.setOrientation("vertical");
			addCartButton.setIcon(ADD_CART_ICON);

			addCartButton.addClickHandler(new ClickHandler() {

				@Override
				public void onClick(ClickEvent event) {

					final AddCartPrompt addCartPrompt = new AddCartPrompt();
					addCartPrompt.show();
					addPromptHandlers(addCartPrompt);
				}
			});
		}
		return addCartButton;
	}

	/**
	 * Link the cart creation prompt to the cart creation behaviour
	 * 
	 * @param addCartPrompt
	 *            The prompt
	 */
	public void cartCreationBehaviour(AddCartPrompt addCartPrompt) {

		String cartName = addCartPrompt.getTextItem().getValueAsString();
		String budget = addCartPrompt.getBudgetItem().getValueAsString();

		if (budget == null)
			SC.warn(ERROR_NULL_BUDGET);

		try {
			getProjectService().addCategory(projectName, cartName,
					Double.valueOf(budget));
			addCartWidget(cartName);
			addCartPrompt.destroy();
		} catch (FrameworkException e) {
			handlerCartCreationException(addCartPrompt, e);
		} catch (NumberFormatException e) {
			handlerCartCreationException(addCartPrompt, e);
		}
	}

	private void handlerCartCreationException(AddCartPrompt addCartPrompt,
			Throwable e) {
		SC.warn(e.getLocalizedMessage());
		addCartPrompt.getValidateButton().setDisabled(false);
		addCartPrompt.getTextItem().focusInItem();
	}

	private void addCartWidget(final String cartName) {

		final Portlet portlet = new Portlet();
		portlet.addCloseClickHandler(new CloseClickHandler() {
			@Override
			public void onCloseClick(CloseClickEvent event) {
				SC.ask(CLOSE_CONFIRMATION_TITLE, CLOSE_CONFIRMATION_MSG,
						new BooleanCallback() {

							@Override
							public void execute(Boolean value) {
								if (value.equals(Boolean.TRUE)) {
									getProjectService().removeCategory(
											projectName, cartName);
									portlet.destroy();
								}

							}

						});

			}
		});
		portlet.setOverflow(Overflow.VISIBLE);
		portlet.addItem(new CartWidget(projectName, cartName));

		String budget = NumberFormat.getCurrencyFormat().format(
				getProjectService().getBudget(projectName, cartName));

		portlet.setTitle(cartName + " - " + budget);
		portlet.setVisible(true);
		portlet.show();
		portalLayout.addPortlet(portlet, 0, portalLayout.getPortlets().length);
	}

	/**
	 * Getter for the project name
	 * 
	 * @return The project name
	 */
	public String getProjectName() {
		return projectName;
	}

	private ProjectService getProjectService() {
		return Services.getInstance().getProjectService();
	}

}